package com.easyaop.asm.bytecode.asm.methodvisitor;

import com.easyaop.commons.MyLoader;
import com.easyaop.asm.bytecode.ByteUtils;
import com.easyaop.asm.bytecode.MethodInfo;
import javassist.*;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class AroundComplieBuilder implements Opcodes {

    static AtomicInteger integer = new AtomicInteger(0);

    static MyLoader loader = new MyLoader(AroundComplieBuilder.class.getClassLoader());
    static ClassPool classPool = ClassPool.getDefault();

    static {
        classPool.importPackage("org.objectweb.asm.MethodVisitor");
        classPool.importPackage("org.objectweb.asm.AnnotationVisitor");
        classPool.importPackage("org.objectweb.asm.Label");
        classPool.importPackage("org.objectweb.asm.Handle");
        classPool.importPackage("org.objectweb.asm.Opcodes");
        classPool.importPackage("org.objectweb.asm.Type");
    }

    public static DefaultMethodVisitorCompile to(MethodInfo methodInfo){
        String body = methodInfo.getBody();

        String className = "javassist.temp.AopComplie_" + integer.getAndDecrement();
        try {

            CtClass ctClass = classPool.makeClass(className);
            ctClass.addInterface(classPool.getCtClass(MethodVisitorCompile.class.getName()));
            ctClass.addInterface(classPool.getCtClass(Opcodes.class.getName()));

            CtMethod make = CtNewMethod.make("public void execute(MethodVisitor classWriter){"
                    +"AnnotationVisitor annotationVisitor0 =null;"
                    + body
                    + "}", ctClass);

            ctClass.addMethod(make);

            byte[] bytes = ctClass.toBytecode();
            Class<?> aClass = loader.loadClass(className, bytes);
            MethodVisitorCompile methodVisitorCompile = (MethodVisitorCompile) aClass.newInstance();
            DefaultMethodVisitorCompile proxyMethodVisitorComplie = new DefaultMethodVisitorCompile(methodVisitorCompile,methodInfo);
//            proxyMethodVisitorComplie.setMethodInfo(methodInfo);

            return proxyMethodVisitorComplie;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static DefaultMethodVisitorCompile to(byte[] aroundByte) {
        ByteUtils byteUtils = new ByteUtils();
        List<MethodInfo> methodInfoList = byteUtils.read(aroundByte, "around", null, ClassReader.SKIP_FRAMES);

        return to(methodInfoList.get(0));
    }
}
